home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_08_11 / 8n11066a < prev    next >
Text File  |  1990-07-26  |  4KB  |  162 lines

  1. // npx.cpp - Non-Preemptive eXecutive
  2. //           Copyright 1990 by Cnapse
  3. //           Written by: M. de Champlain
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7.  
  8. #include "npx.hpp"
  9.  
  10. Task   *running;
  11.  
  12. // ---- base class StateQ -------------------
  13. class StateQ {
  14. friend class ReadyQ;
  15.     Task      *header;
  16.     taskState  state;
  17. public:
  18.     StateQ(int nTasks, taskState st);
  19.     void Insert(Task *thisTask);
  20.     void Transfer(Task *thisTask);
  21.     ~StateQ( );
  22. };
  23.  
  24. inline StateQ::StateQ(int nTasks, taskState st) 
  25.      { 
  26.      header = List_Allocate(nTasks, sizeof(Task));
  27.      state  = st;
  28.      }
  29.  
  30. inline void StateQ::Insert(Task *thisTask)
  31.      {
  32.      thisTask->state = state;
  33.      List_InsertTail(thisTask, header);
  34.      }
  35.  
  36. inline void StateQ::Transfer(Task *thisTask)
  37.      {
  38.      thisTask->state = state;
  39.      List_Remove(thisTask);
  40.      List_InsertTail(thisTask, header);
  41.      }
  42.  
  43. inline StateQ::~StateQ() 
  44.      { 
  45.      List_Free( header );
  46.      }
  47.  
  48. // ---- derived class ReadyQ -------------------
  49.  
  50. class ReadyQ : StateQ {
  51. public:
  52.     ReadyQ() : StateQ(0, READY) {}
  53.     void GetNextRunning(void);
  54. };
  55.  
  56. inline void ReadyQ::GetNextRunning(void)
  57.      {
  58.      (running = List_RemoveHead(header))->state = RUNNING;
  59.      }
  60.  
  61. StateQ *terminatedQ, *suspendedQ;
  62. ReadyQ *readyQ;
  63.  
  64. Task *Task::Start(void)
  65.     {
  66.     if (stackBase = new word[stackSizeInBytes/2])
  67.         {
  68.         /* establish new task's SP */
  69.         sp = (reg)((word)stackBase + stackSizeInBytes);
  70.         *--sp = (word) taskStartingAddress;  
  71.         --sp;                     /* push bp */
  72.         parent = running;
  73.         self   = this;
  74.         readyQ->Insert(this);
  75.         return self;
  76.         }
  77.     else
  78.         return 0;
  79.     }
  80.  
  81. Task *Task::Self(void)
  82.     {
  83.     return self;
  84.     }
  85.  
  86. Task *Task::Parent(void)
  87.     {
  88.     return parent;
  89.     }
  90.  
  91. void Task::Schedule(void)
  92.     {
  93.     readyQ->GetNextRunning();  // assume at least one task is READY 
  94.     }
  95.  
  96. extern void ContextSwitch(void);
  97. extern void RunNext(void);
  98. reg *addrRunningTcbSp;
  99.  
  100. void Task::ReSchedule(void)
  101.     {
  102.     // save the address of the runningTcb's stack ptr for ContextSwitch.
  103.     addrRunningTcbSp = &running->sp; 
  104.     // put the running task in the READY queue
  105.     readyQ->Insert(running);
  106.     Schedule();
  107.     ContextSwitch();
  108.     }
  109.  
  110. void Task::Terminate(Task *id)
  111.     {
  112.     if ( id->state != TERMINATED )
  113.         {
  114.         delete id->stackBase;
  115.         terminatedQ->Transfer(id);
  116.         delete id;
  117.         if ( id == running )
  118.             {
  119.             Schedule();
  120.             RunNext();
  121.             // should never back here
  122.             }
  123.         }
  124.     }
  125.  
  126. void Task::Suspend(Task *id)
  127.     {
  128.     if ( id->state != SUSPENDED )
  129.         {
  130.         suspendedQ->Transfer(id);
  131.         if ( id == running )
  132.             {
  133.             // save address of the runningTcb's stack ptr for ContextSwitch.
  134.             addrRunningTcbSp = &running->sp; 
  135.             Schedule();
  136.             ContextSwitch();
  137.             // will come back here after a Resume
  138.             }
  139.         }
  140.     }
  141.  
  142. void Task::Resume(Task *id)
  143.     {
  144.     if ( id->state == SUSPENDED )
  145.         readyQ->Transfer(id);
  146.     }
  147.  
  148. extern void StartUpUserTasks(void);
  149.  
  150. main(void)
  151.     {
  152.     printf("Non-Preemptive eXecutive, Copyright 1990 by Cnapse\n\n");
  153.     terminatedQ = new StateQ(10, TERMINATED );
  154.     suspendedQ  = new StateQ( 0, SUSPENDED  );
  155.     readyQ      = new ReadyQ();
  156.  
  157.     // Make StartUpUserTasks RUNNING 
  158.     (new Task(StartUpUserTasks, 1024))->Start();
  159.     readyQ->GetNextRunning();
  160.     RunNext();
  161.     }
  162.